// =====================================================================================
// 
//       Filename:  Mare.hh
// 
//    Description:  Implementazione della classe Mare
// 
//         Author:  Davide Poletti , davide.pole@gmail.com
//					Paolo Pigato , p.pigato@hotmail.com	
//        Company:  P&P.cpp
// 
// =====================================================================================

#include "Mare.hh"

Mare::Mare()
{
    _caselle = vector<vector<Casella> > (0,vector<Casella> (0));
}

Mare::Mare(int n, bool mio)
{	    
    _caselle = vector<vector<Casella> >(n, vector<Casella>(n, Casella(mio)));
}


Mare::~Mare()
{;}

int Mare::subisci_sparo(pair<int, int> coor)
{
    int esito = (*this)[coor]->subisci_sparo();
    return esito;
}

int Mare::dim_mare() const
{
    return _caselle.size();
}

bool Mare::in_mare(pair<int, int> p) const
{
    bool test =  (p.first >= 0 && p.second >= 0 && p.first < dim_mare() && p.second < dim_mare());
    return test;
}

pair<int,int> Mare::vai_successiva(pair<int,int> p,int angle) const
{
    pair<int,int> succ = p;	
    angle = angle % 4;	
    switch (angle) {
        case 0: succ.second++;
                break;
        case 1: succ.first++;
                break;
        case 2: succ.second--;
                break;
        case 3: succ.first--;
                break;
        default: cout << "Mare: errore, angolo non contemplato"<<endl;
                 break;   
    }
    return	succ;
}	

bool Mare::test_casella(pair<int,int> coor) const
{
    bool test = true;	
    if (in_mare(coor)){
        if((*this)[coor]->nave_qui()){
            test = false;
        } else {  
            for ( int i = 0; i < 4; i++){
                pair<int, int> coor_vic = vai_successiva(coor , i);			
                if (in_mare(coor_vic)){
                    if((*this)[coor_vic]->nave_qui()){
                        test = false;
                    }  
                }
                coor_vic = vai_successiva(coor_vic , (i+1)%4);
                if (in_mare(coor_vic)){
                    if((*this)[coor_vic]->nave_qui()){
                        test = false;
                    }  
                }
            }
        }
    } else {
        test = false;
    }
    return test;
}


Casella* Mare::operator[] (pair<int,int> coor) const
{ 
    const Casella* c = &_caselle[coor.second][coor.first];
    return const_cast<Casella*>(c);
}

bool Mare::ci_sta_nave(pair<int, int> coor, int orient, int dim) const
{
    bool test = true;
    pair<int,int> c = coor;
    for (int i = 0; i < dim; i++){
        test = (test && test_casella(c));
        c = vai_successiva(c, orient);
    }
    return test;
}


void Mare::inserisci_nave(Nave* nave)
{
    pair<int,int> coor = nave->posizione();	
    int dim = nave->dimensione();
    int angle = nave->orientamento();
    for ( int i = 0; i < dim; i++){
        (*this)[coor]->punta_nave(nave);
        coor = vai_successiva(coor, angle);
    }
}

std::ostream& operator<<(std::ostream& os, const Mare& mare){
    int dim = mare.dim_mare();
    vector<vector<Casella> > caselle = mare._caselle;
    vector<vector<Casella> >::iterator riga;
    vector<Casella>::iterator casella;
    os << "   |";
    for (int i = 1; i <= dim ; i++){
        if (i > 9){
            os << " " << i;

        } else{ 
            os << "  " << i;
        }
    }
    os << " <-x" << endl;
    os << "___|";
    for (int i = 1; i <= dim ; i++){
        os << "___";
    }
    os << endl;
    int i = 1;
    for (riga = caselle.begin(); riga != caselle.end(); riga++){
        if (i > 9){
            os << " " << i;

        } else{ 
            os << "  " << i;
        }
        os << "|  ";
        copy((*riga).begin(), (*riga).end(), ostream_iterator<Casella, char>(os, "  "));
        os << endl;
        i++;
    }
    os << "  ^"<< endl << "  y" << endl;
    return os;
}
